/**
 *    Copyright 2012 Geensoft S.A.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/
package ar.com.greensoft.neosystem.dao.jpa;

import java.util.Collection;

import javax.ejb.Stateless;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Root;

import ar.com.greensoft.neosystem.dao.DaoException;
import ar.com.greensoft.neosystem.dao.UserDao;
import ar.com.greensoft.neosystem.model.Authority;
import ar.com.greensoft.neosystem.model.AuthorityId;
import ar.com.greensoft.neosystem.model.User;
import ar.com.greensoft.neosystem.model.User_;
import ar.com.greensoft.neosystem.search.SearchFilter;
import ar.com.greensoft.neosystem.util.SearchUtil;

/**
*
* @author Jorge E. Villaverde
* @since 1.0
*/
@Stateless
public class JpaUserDaoImpl 
	extends CommonJpaDaoImpl<User, String> 
	implements UserDao {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	@Override
	public User findUserByUsername(String username) throws DaoException {
		username = SearchUtil.likeString(username); 
		
		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
		
		CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);
		Root<User> root = criteriaQuery.from(User.class);
		
		criteriaQuery.select(root);
		
		criteriaQuery.where(
				criteriaBuilder.or(
						criteriaBuilder.like(root.get(User_.username), username)));
					
		TypedQuery<User> typedQuery = entityManager.createQuery(criteriaQuery);
		
		try {
			return typedQuery.getSingleResult();
		} catch (NoResultException e) {
			logger.error("Error finding " + getClass().getSimpleName());
		} catch (NonUniqueResultException e) {
			logger.error("Error finding " + getClass().getSimpleName());
		}
		return null;
	}

	@Override
	public void addAuthority(Authority authority) throws DaoException {
		if(logger.isTraceEnabled())
			logger.trace("Granting Authority: " + authority.getAuthority() + " to User: " + authority.getUser().getUsername());
		entityManager.persist(authority);		
	}


	@Override
	public void removeAuthority(Authority authority) throws DaoException {
		if(logger.isTraceEnabled())
			logger.trace("Removing Authority: " + authority.getAuthority() + " from User: " + authority.getUser().getUsername());
		entityManager.remove(authority);		
	}

	@Override
	public void removeAuthority(User user, String authority) throws DaoException {
		if(logger.isTraceEnabled())
			logger.trace("Removing Authority: " + authority + " from User: " + user.getUsername());
		
		AuthorityId id = new AuthorityId();
		id.setUser(user);
		id.setAuthority(authority);
		
		Authority auth = entityManager.find(Authority.class, id);
		
		entityManager.remove(auth);
	}

	protected Class<User> getEntityClazz() {
		return User.class;
	}
				
	@Override
	public User findById(String id) {
		if(logger.isTraceEnabled())
			logger.trace("Returning entity of type: " + getEntityClazz().getSimpleName() + "\twith id: " + id);
		return entityManager.find(getEntityClazz(), id);
	}	
			
	protected Collection<User> findByCriteria(CriteriaQuery<User> criteria) {
		TypedQuery<User> typedQuery = entityManager.createQuery(criteria);
		return typedQuery.getResultList();
	}

	@Override
	public User findByName(String name) {
		try {
			return findUserByUsername(name);
		} catch (DaoException e) {
		}
		return null;
	}

	@Override
	protected Expression<Boolean> createWhereFromSearchFilter(SearchFilter searchFilter, Root<User> root) {
		return null;
	}
}
